package com.liy.supercloud.server.gateway.exp;

import com.liy.supercloud.server.gateway.filter.MyGlobalFilter;
import com.liy.supercloud.server.gateway.task.GatewayCountTimer;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;

public class JsonErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {
    Logger logger = LoggerFactory.getLogger(MyGlobalFilter.class);

    public JsonErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }

    protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
        GatewayCountTimer.getNextRequestFailureNumber();
        Throwable error = super.getError(request);
        Long startTime = (Long)request.exchange().getAttribute("startTime");
        if (startTime != null) {
            Long executeTime = System.currentTimeMillis() - startTime;
            this.logger.info(request.path() + " : " + executeTime + "ms");
        }

        Map<String, Object> errorAttributes = new HashMap(4);
        errorAttributes.put("message", error.getMessage());
        errorAttributes.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
        errorAttributes.put("method", request.methodName());
        errorAttributes.put("path", request.path());
        return errorAttributes;
    }

    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
    }

    protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
        int statusCode = (Integer)errorAttributes.get("status");
        return HttpStatus.valueOf(statusCode);
    }
}
